package com.eshop.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.FileReader;
import org.apache.poi.util.IOUtils;
import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.io.FileNotFoundException;
import com.eshop.exception.BadRequestException;
import javax.servlet.ServletOutputStream;
import cn.hutool.poi.excel.BigExcelWriter;
import java.io.Closeable;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.List;
import cn.hutool.core.codec.Base64;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import cn.hutool.core.util.IdUtil;
import java.io.File;
import org.springframework.web.multipart.MultipartFile;
import java.text.DecimalFormat;

public class FileUtil extends cn.hutool.core.io.FileUtil
{
    private static final int GB = 1073741824;
    private static final int MB = 1048576;
    private static final int KB = 1024;
    private static final DecimalFormat DF;
    
    public static File toFile(final MultipartFile multipartFile) {
        final String fileName = multipartFile.getOriginalFilename();
        final String prefix = "." + getExtensionName(fileName);
        File file = null;
        try {
            file = File.createTempFile(IdUtil.simpleUUID(), prefix);
            multipartFile.transferTo(file);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }
    
    public static String getExtensionName(final String filename) {
        if (filename != null && filename.length() > 0) {
            final int dot = filename.lastIndexOf(46);
            if (dot > -1 && dot < filename.length() - 1) {
                return filename.substring(dot + 1);
            }
        }
        return filename;
    }
    
    public static String getFileNameNoEx(final String filename) {
        if (filename != null && filename.length() > 0) {
            final int dot = filename.lastIndexOf(46);
            if (dot > -1 && dot < filename.length()) {
                return filename.substring(0, dot);
            }
        }
        return filename;
    }
    
    public static String getSize(final long size) {
        String resultSize;
        if (size / 1073741824L >= 1L) {
            resultSize = FileUtil.DF.format(size / 1.07374182E9f) + "GB   ";
        }
        else if (size / 1048576L >= 1L) {
            resultSize = FileUtil.DF.format(size / 1048576.0f) + "MB   ";
        }
        else if (size / 1024L >= 1L) {
            resultSize = FileUtil.DF.format(size / 1024.0f) + "KB   ";
        }
        else {
            resultSize = size + "B   ";
        }
        return resultSize;
    }
    
    public static File inputStreamToFile(final InputStream ins, final String name) throws Exception {
        final File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
        if (file.exists()) {
            return file;
        }
        final OutputStream os = new FileOutputStream(file);
        final int len = 8192;
        final byte[] buffer = new byte[len];
        int bytesRead;
        while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        ins.close();
        return file;
    }
    
    public static File upload(final MultipartFile file, final String filePath) {
        final String suffix = getExtensionName(file.getOriginalFilename());
        final StringBuffer nowStr = fileRename();
        try {
            final String fileName = (Object)nowStr + "." + suffix;
            final String path = filePath + fileName;
            final File dest = new File(path).getCanonicalFile();
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            file.transferTo(dest);
            return dest;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static String fileToBase64(final File file) throws Exception {
        final FileInputStream inputFile = new FileInputStream(file);
        final byte[] buffer = new byte[(int)file.length()];
        inputFile.read(buffer);
        inputFile.close();
        final String base64 = Base64.encode(buffer);
        return base64.replaceAll("[\\s*\t\n\r]", "");
    }
    
    public static void downloadExcel(final List<Map<String, Object>> list, final HttpServletResponse response) throws IOException {
        final String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
        final File file = new File(tempPath);
        final BigExcelWriter writer = ExcelUtil.getBigWriter(file);
        writer.write((Iterable)list, true);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
        final ServletOutputStream out = response.getOutputStream();
        file.deleteOnExit();
        writer.flush((OutputStream)out, true);
        IoUtil.close((Closeable)out);
    }
    
    public static String getFileType(final String type) {
        final String documents = "txt doc pdf ppt pps xlsx xls docx";
        final String music = "mp3 wav wma mpa ram ra aac aif m4a";
        final String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
        final String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
        if (image.contains(type)) {
            return "pic";
        }
        if (documents.contains(type)) {
            return "txt";
        }
        if (music.contains(type)) {
            return "music";
        }
        if (video.contains(type)) {
            return "vedio";
        }
        return "other";
    }
    
    public static void checkSize(final long maxSize, final long size) {
        final int len = 1048576;
        if (size > maxSize * len) {
            throw new BadRequestException("文件超出规定大小");
        }
    }
    
    public static boolean check(final File file1, final File file2) {
        final String img1Md5 = getMd5(file1);
        final String img2Md5 = getMd5(file2);
        return img1Md5.equals(img2Md5);
    }
    
    public static boolean check(final String file1Md5, final String file2Md5) {
        return file1Md5.equals(file2Md5);
    }
    
    private static byte[] getByte(final File file) {
        final byte[] b = new byte[(int)file.length()];
        try {
            final InputStream in = new FileInputStream(file);
            try {
                in.read(b);
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        catch (FileNotFoundException e2) {
            e2.printStackTrace();
            return null;
        }
        return b;
    }
    
    private static String getMd5(final byte[] bytes) {
        final char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            final MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(bytes);
            final byte[] md = mdTemp.digest();
            final int j = md.length;
            final char[] str = new char[j * 2];
            int k = 0;
            for (final byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xF];
                str[k++] = hexDigits[byte0 & 0xF];
            }
            return new String(str);
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static void downloadFile(final HttpServletRequest request, final HttpServletResponse response, final File file, final boolean deleteOnExit) {
        response.setCharacterEncoding(request.getCharacterEncoding());
        response.setContentType("application/octet-stream");
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
            IOUtils.copy((InputStream)fis, (OutputStream)response.getOutputStream());
            response.flushBuffer();
        }
        catch (Exception e) {
            e.printStackTrace();
            if (fis != null) {
                try {
                    fis.close();
                    if (deleteOnExit) {
                        file.deleteOnExit();
                    }
                }
                catch (IOException e2) {
                    e2.printStackTrace();
                }
            }
        }
        finally {
            if (fis != null) {
                try {
                    fis.close();
                    if (deleteOnExit) {
                        file.deleteOnExit();
                    }
                }
                catch (IOException e3) {
                    e3.printStackTrace();
                }
            }
        }
    }
    
    public static String getMd5(final File file) {
        return getMd5(getByte(file));
    }
    
    public static String readJsonFile(final String fileName) {
        String jsonStr = "";
        try {
            final File jsonFile = new File(fileName);
            final FileReader fileReader = new FileReader(jsonFile);
            final Reader reader = new InputStreamReader(new FileInputStream(jsonFile), "utf-8");
            int ch = 0;
            final StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char)ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        }
        catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static BufferedImage inputImage(final MultipartFile file) {
        BufferedImage srcImage = null;
        try {
            final FileInputStream in = (FileInputStream)file.getInputStream();
            srcImage = ImageIO.read(in);
        }
        catch (IOException e) {
            System.out.println("读取图片文件出错！" + e.getMessage());
        }
        return srcImage;
    }
    
    public static float getAccuracy(final long size) {
        float accuracy;
        if (size < 400L) {
            accuracy = 0.85f;
        }
        else if (size < 900L) {
            accuracy = 0.75f;
        }
        else if (size < 2047L) {
            accuracy = 0.6f;
        }
        else if (size < 3275L) {
            accuracy = 0.44f;
        }
        else {
            accuracy = 0.4f;
        }
        return accuracy;
    }
    
    public static StringBuffer fileRename() {
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        final String time = sdf.format(new Date());
        final StringBuffer buf = new StringBuffer(time);
        final Random r = new Random();
        for (int x = 0; x < 3; ++x) {
            buf.append(r.nextInt(10));
        }
        return buf;
    }
    
    public static String transformStyle(final String source) throws UnsupportedEncodingException {
        final char[] arr = source.toCharArray();
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; ++i) {
            final char temp = arr[i];
            if (isChinese(temp)) {
                sb.append(URLEncoder.encode("" + temp, "UTF-8"));
            }
            else {
                sb.append(arr[i]);
            }
        }
        return sb.toString();
    }
    
    public static boolean isChinese(final char c) {
        final Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
    }
    
    static {
        DF = new DecimalFormat("0.00");
    }
}
